package gcommand

import (
	. "Ghost/utd"
	"Ghosted/pack"
	"fmt"
	"github.com/lxn/walk"
	"sort"
)

var TheModel *MainModel = &MainModel{centers: &ModelCenter{}, nodes: &ModelNode{}, input: &ModelInput{}}

type MainModel struct {
	dbind      *walk.DataBinder
	ServerInfo string
	centers    *ModelCenter
	nodes      *ModelNode
	input      *ModelInput
}

func (this *MainModel) CenterTableModel() interface{} { return this.centers }
func (this *MainModel) NodeTableModel() interface{}   { return this.nodes }
func (this *MainModel) CmdInputModel() interface{}    { return this.input }
func (this *MainModel) ResetBinder(reset bool) {
	UHelp.IFCast(this.dbind != nil && reset, func() { this.dbind.Reset() }, nil)
}
func (this *MainModel) SetServerInfo(s string, reset bool) {
	this.ServerInfo = s
	this.ResetBinder(reset)
}

type ModelCenter struct {
	walk.TableModelBase
	walk.SorterBase
	sortColumn int
	sortOrder  walk.SortOrder
	items      []*pack.PtNetNode
}

func (this *ModelCenter) RowCount() int { return len(this.items) }

func (this *ModelCenter) Value(row, col int) interface{} {
	item := this.items[row]

	switch col {
	case 0:
		return item.ServerId

	case 1:
		return item.ServerName

	case 2:
		return fmt.Sprintf("%s:%d", item.ListenIP, item.ListenPort)
	}

	panic("unexpected col")
}
func (this *ModelCenter) Sort(col int, order walk.SortOrder) error {
	this.sortColumn, this.sortOrder = col, order

	sort.SliceStable(this.items, func(i, j int) bool {
		a, b := this.items[i], this.items[j]

		c := func(ls bool) bool {
			if this.sortOrder == walk.SortAscending {
				return ls
			}
			return !ls
		}

		switch this.sortColumn {
		case 0:
			return c(a.ServerId < b.ServerId)

		case 1:
			return c(a.ServerName < b.ServerName)

		case 2:
			return c(a.ListenPort < b.ListenPort)
		}

		panic("unreachable")
	})

	return this.SorterBase.Sort(col, order)
}
func (this *ModelCenter) UpdateData(items []*pack.PtNetNode) {
	this.items = items

	this.PublishRowsReset()

	this.Sort(this.sortColumn, this.sortOrder)
}

type ModelNode struct {
	walk.TableModelBase
	walk.SorterBase
	sortColumn int
	sortOrder  walk.SortOrder
	items      []*pack.PtNetNode
}

func (this *ModelNode) RowCount() int { return len(this.items) }

func (this *ModelNode) Value(row, col int) interface{} {
	item := this.items[row]

	switch col {
	case 0:
		return item.ServerId

	case 1:
		return item.ServerName

	case 2:
		return fmt.Sprintf("%s:%d", item.ListenIP, item.ListenPort)
	}

	panic("unexpected col")
}
func (this *ModelNode) Sort(col int, order walk.SortOrder) error {
	this.sortColumn, this.sortOrder = col, order

	sort.SliceStable(this.items, func(i, j int) bool {
		a, b := this.items[i], this.items[j]

		c := func(ls bool) bool {
			if this.sortOrder == walk.SortAscending {
				return ls
			}
			return !ls
		}

		switch this.sortColumn {
		case 0:
			return c(a.ServerId < b.ServerId)

		case 1:
			return c(a.ServerName < b.ServerName)

		case 2:
			return c(a.ListenPort < b.ListenPort)
		}

		panic("unreachable")
	})

	return this.SorterBase.Sort(col, order)
}
func (this *ModelNode) UpdateData(items []*pack.PtNetNode) {
	this.items = items

	this.PublishRowsReset()

	this.Sort(this.sortColumn, this.sortOrder)
}

type ModelInput struct {
	walk.ListModelBase
	recordList []string
}

func (this *ModelInput) ItemCount() int { return len(this.recordList) }

func (this *ModelInput) Value(index int) interface{} { return this.recordList[index] }

func (this *ModelInput) Insert(str string) {
	if len(this.recordList) < 10 {
		this.recordList = append(this.recordList, str)
	}
	if count := len(this.recordList); true {
		for i := 1; i < count; i++ {
			this.recordList[count-i] = this.recordList[count-i-1]
		}
		this.recordList[0] = str
	}
	this.PublishItemsReset()
}
